#ifndef GAMEENGINE_GEOMETRY_TRGL2DFAST_H
#define GAMEENGINE_GEOMETRY_TRGL2DFAST_H

#include <GameEngine/Geometry/geometry_settings.h>

#include <GameEngine/Geometry/Location/point2d.h>
#include <GameEngine/Geometry/Location/vector2d.h>
#include <GameEngine/Geometry/Lines/line2d.h>
#include <GameEngine/Geometry/Core/coords2d.h>
#include <GameEngine/Geometry/CoordinateSystems/transformer2d.h>

#include <GameEngine/Geometry/Surfaces/trgl2d_defs.h>


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

//! Class used for fast computations on 2D triangles
/*!
 *  This class is quite similar to the Trgl2d class and shares most of its interface. The
 *  most notable difference, however, is the strategy for memory management: while the
 *  Trgl2d class stores the geometry of the three associated points, the Trgl2dFast class
 *  only uses references and is therefore much faster to build. This, naturally, comes with
 *  some constraints:<br>
 *  1. It is not possible to have a default constructor nor a copy of a Trgl2dFast item,<br>
 *  2. The geometry of the points associated to Trgl2dFast items can not be modified, and<br>
 *  3. The points used in the Trgl2dFast item should never be destroyed before the Trgl2dFast
 *     item itself, otherwise data access will corrupt memory / result in application crashes.
 *
 *  Generally, it is recommanded to use this class rather than the Trgl2d class when client
 *  code requires only on-the-fly geometric queries.
 *
 @note A 2D triangle is made of three 2D points
 @note Most algorithms expect floating point operations. Type T should therefore
       not be an integer type
 */
template <class T>
class Trgl2dFast {

public:
	Trgl2dFast(const Point2d<T>& p1, const Point2d<T>& p2, const Point2d<T>& p3);
	virtual ~Trgl2dFast();

	const Point2d<T>& p1() const;
	const Point2d<T>& p2() const;
	const Point2d<T>& p3() const;

	Vector2d<T> u_axis() const;
	Vector2d<T> v_axis() const;

	Point2d<T> point(const Coords2d<T>& coords) const;
	Coords2d<T> coordinates(const Point2d<T>& pt) const;
	Transformer2d<T> transformer() const;

	const Point2d<T>& operator[](Trgl2D::Index index) const;

	bool inside(const Point2d<T>& rhs, bool strict = false) const;
	bool intersection(const Line2d<T>& rhs, T& line_coordinate1, T& line_coordinate2, IntersectionType::Type* type = nil) const;
	bool closest_point(const Point2d<T>& rhs, Coords2d<T>& coords) const;
	Point2d<T> closest_point(const Point2d<T>& rhs) const;

	T perimeter() const;
	T area() const;

	bool degenerate(const T& tolerance = 0.000001) const;
	static bool in_trgl(const Coords2d<T>& coords, bool strict=false);

protected:
	//! First point
	const Point2d<T>& p1_;

	//! Second point
	const Point2d<T>& p2_;

	//! Third point
	const Point2d<T>& p3_;
};

#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif

#include <GameEngine/Geometry/Surfaces/trgl2dfast.hpp>

#endif
